// 模拟Java的future模式
package channel

import (
	"errors"
	"time"
)

// 任务接口
type FutureTask interface {
	run() (interface{}, error)
}

// future 实现类（只内部创建实例）
type future func(duration time.Duration) (interface{}, error)

//阻塞等待返回结果
func (f future) Get() (interface{}, error) {
	return f(0)
}

//超时获取
func (f future) GetTimeout(timeout time.Duration) (interface{}, error) {
	return f(timeout)
}


// future 结果（channel只能获取单个结果，故用个内部结构体解决多值返回问题）
type FutureResult struct {
	result interface{}
	err    error
}

//
//
// @Param taskF 任务逻辑函数
// @Param args 传给任务逻辑函数的参数
//
// @Return future
//
func DoFutureTask(taskF FutureTask) future {

	c := make(chan FutureResult, 1)
	go func() {
		defer close(c)
		result, err := taskF.run()
		c <- FutureResult{
			result: result,
			err:    err,
		}
	}()

	return func(timeout time.Duration) (interface{}, error) {

		if timeout > 0 {
			// select 是按顺序判断执行，故先判断是否超时
			select {
			case <-time.After(timeout):
				return nil, errors.New("future timeout")
			case fr := <-c:
				return fr.result, fr.err
			}
		} else {
			fr := <-c
			return fr.result, fr.err
		}
	}
}
